
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.LinkedList;
import kpython.ASTStart;
import kpython.ParseException;
import kpython.Parser;
import kpython.backend.ir.canon.Optimizer;
import kpython.backend.ir.tree.IRNode;
import kpython.backend.ir.tree.IRTreeBuilder;
import kpython.backend.ir.tree.SimpleBlock;
import kpython.backend.semantic.SymbolTable;
import kpython.backend.semantic.SymbolTableBuilder;
import kpython.backend.translator.Translator;

public class Compiler {

    public static void main(String args[]) throws ParseException {
        Parser parser = null;        
        ASTStart astRoot = null;
        SymbolTable symbolTable = null;        
        /*
        if (args.length == 1) {
            try {
            	//Dividir d
            	String[] split = args[0].split(File.separator);            	
            	finalInput(args[0], new LinkedList<String>());
            	reader = new BufferedReader(new StringReader(buffer.toString()));
                parser = new Parser(reader);
            } catch (IOException e) {
                System.err.println("FILE NOT FOUND ERROR: " + e.getLocalizedMessage());
                e.printStackTrace();
                System.exit(0);
            }
        } else */
        if (args.length == 0) {
        	try {
        		System.out.println("Generating sintactic file...");
				finalInput("input.kpy", new LinkedList<String>());
				reader = new BufferedReader(new StringReader(buffer.toString()));
				System.out.println("-- Final Input File --");
				System.out.println(buffer.toString());
				System.out.println("--------- END --------");        		
				System.out.println("Generating sintactic file... Completed");
				parser = new Parser(reader);
			} catch (IOException e) {
				System.err.println("FILE NOT FOUND ERROR: " + e.getLocalizedMessage());
				e.printStackTrace();
	            System.exit(0);
			}            
        }
        try {
        	System.out.println("Sintactic Analysis...");
            astRoot = parser.Start();
            
                
            if (parser.token_source.nErrors > 0) {
                System.out.println("Sintactic errors found (" + parser.token_source.nErrors + ").");
            } else {
                System.out.println("Sintactic Analysis... Completed");
                System.out.println("Semantic Analysis...");
                System.out.println("---- Abstract Sintax Tree -----");
                astRoot.dump("");
                System.out.println("------------- END -------------");
                SymbolTableBuilder semantic = new SymbolTableBuilder();
                symbolTable = (SymbolTable) semantic.visit(astRoot, null);
                System.out.println("Semantic Analysis... Completed");
                symbolTable.printTable();
                if (!semantic.hasErrors()) {
                    IRTreeBuilder intermediateTreeBuilder = new IRTreeBuilder();
                    System.out.println("Generating Intermediate Tree Representation... ");
                    IRNode tree = (IRNode) intermediateTreeBuilder.visit(astRoot, null);
                    System.out.println("Generation of Intermediate Tree Representation... Completed");
                    System.out.println("--------- IR Tree ---------");
                    tree.printTree("");
                    System.out.println("----------- End -----------");
                    Optimizer optimizer = new Optimizer();
                    System.out.println("Optimizing Intermediate Tree Representation... ");
                    IRNode canonTree = (IRNode) optimizer.initOptimizer((SimpleBlock)tree);
                    System.out.println("Optimization Intermediate Tree Representation... Completed");
                    System.out.println("--------- IR Tree ---------");
                    canonTree.printTree("");
                    System.out.println("----------- End -----------");                    
                    System.out.println("Translating to C...");
                    Translator translate = new Translator();
                    translate.initTranslation((SimpleBlock)canonTree, symbolTable);
                    System.out.println("Translation to C... Completed");
                    System.out.println("Go to ./data/ and run result.c");
                } else {
                    System.out.println("Semantic errors found: " + semantic.getNumErrors());
                }               
            }
        } catch (Exception e) {
            System.out.println("Error: " + e.getLocalizedMessage());
            e.printStackTrace();
        }
    }
    
    private static LinkedList<String> includedFiles = new LinkedList<String>();     
    private static BufferedReader reader = null;
    private static StringBuffer buffer = new StringBuffer(); 
    private static String path = "data//";
    
    public static void finalInput(String file, LinkedList<String> toInclude) throws IOException {
    		String line;
    		System.out.println("include:: "+path+file);
			File f = new File(path+file);
			BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
			while ((line = reader.readLine()) != null) {				
				if (line.equals("")) {
					continue;
				} else if (line.startsWith("include")) {
					String includedFile = line.replace("include", "").trim();
					if (!includedFiles.contains(includedFile)) {
						toInclude.add(includedFile.substring(1,includedFile.length()-1));
						includedFiles.add(includedFile.substring(1,includedFile.length()-1));
					}
					continue;
				}				
				buffer.append(line+"\n");
			}
			buffer.append("\n");
			reader.close();
			if (!toInclude.isEmpty())
				finalInput(toInclude.removeFirst(), toInclude);					
    }
}
